package me.sdevil507.org.service.impl;

import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import me.sdevil507.biz.common.exceptions.PhoneNumberExistedException;
import me.sdevil507.biz.common.exceptions.UserExistedException;
import me.sdevil507.org.dto.OrgInviteParamsDto;
import me.sdevil507.org.mapper.OrgInviteMapper;
import me.sdevil507.org.po.*;
import me.sdevil507.org.repository.*;
import me.sdevil507.org.service.OrgInviteService;
import me.sdevil507.org.service.OrgUserService;
import me.sdevil507.org.service.TempExpertService;
import me.sdevil507.supports.jpa.PageParamsDTO;
import me.sdevil507.supports.jpa.SortParamsDTO;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.util.RegularExpressionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

/**
 * 邀请记录表[OrgInviteServiceImpl]
 *
 * @author sdevil507
 * created on 2020-08-13 11:39:50
 */
@Service
public class OrgInviteServiceImpl implements OrgInviteService {

    @Resource
    private OrgInviteRepository orgInviteRepository;

    @Autowired
    private OrgRepository orgRepository;

    @Autowired
    private OrgInviteMapper orgInviteMapper;

    @Autowired
    private OrgUserService orgUserService;

    @Autowired
    private OrgUserRepository orgUserRepository;

    @Autowired
    private OrgUserRelRepository orgUserRelRepository;

    @Autowired
    private OrgExpertInfoRepository orgExpertInfoRepository;

    @Autowired
    private TempExpertService tempExpertService;

    @Override
    public Page<OrgInvitePo> readAllByPage(OrgInviteParamsDto searchParamsDto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QOrgInvitePo qOrgInvitePo = QOrgInvitePo.orgInvitePo;

        // 开启谓语查询条件
        Predicate predicate = qOrgInvitePo.id.isNotNull();

        String realName = searchParamsDto.getRealName();

        if (!StringUtils.isEmpty(realName)) {
            predicate = ExpressionUtils.and(predicate, qOrgInvitePo.realName.like("%" + realName + "%"));
        }

        Long orgid = searchParamsDto.getOrgId();
        if (null != orgid && orgid.longValue() > 0) {
            predicate = ExpressionUtils.and(predicate, qOrgInvitePo.orgId.eq(orgid));
        }

        String phoneNumber = searchParamsDto.getPhoneNumber();
        if (!StringUtils.isEmpty(phoneNumber)) {
            predicate = ExpressionUtils.and(predicate, qOrgInvitePo.phoneNumber.like("%" + phoneNumber + "%"));
        }

        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);
        return orgInviteRepository.findAll(predicate, pageable);
    }

    @Override
    public Long inviteUrl(OrgInviteParamsDto dto) {
        OrgInvitePo orgInvitePo = orgInviteMapper.dto2po(dto);
        OrgPo orgPo = orgRepository.findById(OrgAccountHelper.getOrgId()).orElse(null);
        if (orgPo != null) {
            orgInvitePo.setOrgId(orgPo.getId());
            orgInvitePo.setOrgName(orgPo.getNameZh());
        }
        OrgInvitePo savePo = orgInviteRepository.save(orgInvitePo);
        return savePo.getId();
    }

    @Override
    public OrgInvitePo readInvite(Long id) {
        return orgInviteRepository.findById(id).orElse(null);
    }

    @Override
    public OrgInvitePo existedInviteRecord(String phoneNumber, String realName) {
        QOrgInvitePo qOrgInvitePo = QOrgInvitePo.orgInvitePo;
        Predicate predicate = qOrgInvitePo.id.isNotNull()
                .and(qOrgInvitePo.phoneNumber.eq(phoneNumber))
                .and(qOrgInvitePo.realName.eq(realName))
                .and(qOrgInvitePo.orgId.eq(OrgAccountHelper.getOrgId()));
        return orgInviteRepository.findOne(predicate).orElse(null);
    }

    @Override
    public void existed(String phoneNumber) throws UserExistedException, PhoneNumberExistedException {
        if (orgUserService.existsByPhoneNumber(phoneNumber)) {
            // 如果账户已经存在,继续判断是否属于该组织
            QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
            Predicate predicate = qOrgUserRelPo.id.isNotNull()
                    .and(qOrgUserRelPo.user.phoneNumber.eq(phoneNumber))
                    .and(qOrgUserRelPo.org.id.eq(OrgAccountHelper.getOrgId()))
                    .and(qOrgUserRelPo.expert.isTrue());
            OrgUserRelPo orgUserRelPo = orgUserRelRepository.findOne(predicate).orElse(null);
            if (orgUserRelPo != null) {
                // 用户已经在该组织下,提示无需邀请
                throw new UserExistedException("该机构下用户已经存在,且属于该智库!");
            } else {
                // 用户存在,但不在该组织下,提示需要邀请进行与该组织绑定
                throw new PhoneNumberExistedException("该手机号码用户在专家库中已经存在,但不属于该智库!");
            }
        }
    }

    @Override
    public void register(Long id) {
        // 1.提取邀请记录
        OrgInvitePo orgInvitePo = orgInviteRepository.findById(id).orElse(null);
        if (orgInvitePo != null) {
            // 2.封装用户信息入库
            OrgExpertInfoPo orgExpertInfoPo = new OrgExpertInfoPo();
            orgExpertInfoRepository.save(orgExpertInfoPo);
            OrgUserPo orgUserPo = new OrgUserPo();
            orgUserPo.setPhoneNumber(orgInvitePo.getPhoneNumber());
            orgUserPo.setRealName(RegularExpressionUtil.filterSpace(orgInvitePo.getRealName()));
            orgUserPo.setPassword("");
            orgUserPo.setExpertInfo(orgExpertInfoPo);
            OrgUserPo savedUserPo = orgUserRepository.save(orgUserPo);
            // 3.绑定该用户与机构关系
            OrgPo orgPo = orgRepository.findById(orgInvitePo.getOrgId()).orElse(null);
            if (orgPo != null) {
                OrgUserRelPo orgUserRelPo = new OrgUserRelPo();
                orgUserRelPo.setUser(savedUserPo);
//                orgUserRelPo.setOrg(orgPo);
                orgUserRelPo.setFullTime(orgInvitePo.getFullTime());
                orgUserRelPo.setMgr(false);
                orgUserRelPo.setExpert(true);
                orgUserRelRepository.save(orgUserRelPo);
            }
            // 4.设置邀请记录为接受
            orgInvitePo.setAgree(true);
            orgInviteRepository.save(orgInvitePo);
        }
    }

    @Override
    public void bindOrg(Long id) {
        // 1.提取邀请记录
        OrgInvitePo orgInvitePo = orgInviteRepository.findById(id).orElse(null);
        if (orgInvitePo != null) {
            // 2.判断关联关系
            OrgUserRelPo rel = getRel(orgInvitePo.getPhoneNumber(), orgInvitePo.getOrgId());
            if (rel == null) {
                // 如果不存在,新增
                OrgUserPo orgUserPo = orgUserRepository.findByPhoneNumberAndDeletedIsFalse(orgInvitePo.getPhoneNumber());
                OrgPo orgPo = orgRepository.findById(orgInvitePo.getOrgId()).orElse(null);
                if (orgPo != null) {
                    OrgUserRelPo orgUserRelPo = new OrgUserRelPo();
                    orgUserRelPo.setUser(orgUserPo);
//                    orgUserRelPo.setOrg(orgPo);
                    orgUserRelPo.setFullTime(orgInvitePo.getFullTime());
                    orgUserRelPo.setMgr(false);
                    orgUserRelPo.setExpert(true);
                    orgUserRelRepository.save(orgUserRelPo);
                }
            } else if (rel.isMgr() && !rel.isExpert()) {
                // 如果只有管理员角色关系,执行设置专家关系
                rel.setExpert(true);
                orgUserRelRepository.save(rel);
            }
            // 3.设置邀请记录为接受
            orgInvitePo.setAgree(true);
            orgInviteRepository.save(orgInvitePo);
        }
    }

    @Override
    public void reject(Long id) {
        OrgInvitePo orgInvitePo = orgInviteRepository.findById(id).orElse(null);
        if (orgInvitePo != null) {
            if (null == orgInvitePo.getAgree()) {
                orgInvitePo.setAgree(false);
            }
            orgInviteRepository.save(orgInvitePo);
        }
    }

    @Override
    public void removeTemp(Long id) {
        OrgInvitePo orgInvitePo = orgInviteRepository.findById(id).orElse(null);
        if (orgInvitePo != null) {
            if (null != orgInvitePo.getTempExpertId()) {
                // 执行删除临时专家表数据
                OrgUserPo orgUserPo = orgUserRepository.findByPhoneNumberAndDeletedIsFalse(orgInvitePo.getPhoneNumber());
                tempExpertService.temporaryBecomeFormal(orgInvitePo.getTempExpertId(), orgUserPo.getId());
            }
        }
    }

    /**
     * 获取关系
     *
     * @param phoneNumber 手机号
     * @param orgId       机构id
     * @return 关系实体
     */
    @Override
    public OrgUserRelPo getRel(String phoneNumber, Long orgId) {
        QOrgUserRelPo qOrgUserRelPo = QOrgUserRelPo.orgUserRelPo;
        Predicate predicate = qOrgUserRelPo.id.isNotNull()
                .and(qOrgUserRelPo.user.phoneNumber.eq(phoneNumber))
                .and(qOrgUserRelPo.org.id.eq(orgId));
        return orgUserRelRepository.findOne(predicate).orElse(null);
    }

}